<?xml version="1.0" encoding="windows-1250"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" encoding="windows-1250" />

  <xsl:template match="/">
    <problems>
      <xsl:apply-templates select="/node()/Concept/Concept"/>
      <xsl:apply-templates select="/node()/CVInclude/CVInclude"/>
      <xsl:apply-templates select="/node()/CView/CView"/>
      <xsl:apply-templates select="/node()/MenuCat/MenuCat"/>

      <xsl:if test="not(/node()/MenuCat/MenuCat[@name='root'])">
        <problem type="WARNING" resource="Menu" link="menucats/">
          <msg>There should exist menu category named "root".</msg>
        </problem>
      </xsl:if>
    </problems>
  </xsl:template>

  <xsl:template match="Concept">
    <xsl:if test="@name=preceding-sibling::Concept/@name or @name=following-sibling::Concept/@name">
      <problem type="ERROR" resource="Concept: {@name}" link="object_model/?dp=edit100&amp;ID_Concept={@id_concept}">
        <msg>Concept name must be unique.</msg>
      </problem>
    </xsl:if>
    <xsl:if test="@coll=preceding-sibling::Concept/@coll or @coll=following-sibling::Concept/@coll">
      <problem type="ERROR" resource="Concept: {@name}" link="object_model/?dp=edit100&amp;ID_Concept={@id_concept}">
        <msg>Concept collection name must be unique.</msg>
      </problem>
    </xsl:if>
    <xsl:if test="@name=@coll">
      <problem type="WARNING" resource="Concept: {@name}" link="object_model/?dp=edit100&amp;ID_Concept={@id_concept}">
        <msg>Concept name and collection name should be different.</msg>
      </problem>
    </xsl:if>
    <xsl:if test="not(CProperties/CProperty[@key='1'])">
      <problem type="ERROR" resource="Concept: {@name}" link="object_model/?dp=edit100&amp;ID_Concept={@id_concept}">
        <msg>Concept is required to have at least one key property.</msg>
      </problem>
    </xsl:if>
    <xsl:if test="count(CProperties/CProperty[@key='1']) &gt; 1 and not(../Concept/CAssociations/CAssociation[@id_cchild=current()/@id_concept and @type='composite'])">
      <problem type="ERROR" resource="Concept: {@name}" link="object_model/?dp=edit100&amp;ID_Concept={@id_concept}">
        <msg>Concept that is not composite part of other concept must have only one key property.</msg>
      </problem>
    </xsl:if>
    <xsl:if test="CProperties/CProperty[@key='0'] and not(CProperties/CProperty[@key='0' and @onlabel='1'])">
      <problem type="WARNING" resource="Concept: {@name}" link="object_model/?dp=edit100&amp;ID_Concept={@id_concept}">
        <msg>Concept should have some non-key property that is on label.</msg>
      </problem>
    </xsl:if>
    <xsl:if test="count(../Concept/CAssociations/CAssociation[@type='composite' and @id_cchild=current()/@id_concept]) &gt; 1">
      <problem type="ERROR" resource="Concept: {@name}" link="object_model/?dp=edit100&amp;ID_Concept={@id_concept}">
        <msg>There is more than one composite association to this concept!!! 
          (<xsl:for-each select="../Concept/CAssociations/CAssociation[@type='composite' and @id_cchild=current()/@id_concept]">
            <xsl:value-of select="../../@name"/><xsl:text> </xsl:text>
          </xsl:for-each>)
        </msg>
      </problem>
    </xsl:if>
    <xsl:if test="count(../Concept/CAssociations/CAssociation[@type='composite' and @id_cchild=current()/@id_concept])=1 and count(CProperties/CProperty[@key='1'])&lt;2">
      <problem type="ERROR" resource="Concept: {@name}" link="object_model/?dp=edit100&amp;ID_Concept={@id_concept}">
        <msg>Concept in a composite must have also the parent's key included
          (parent: <xsl:for-each select="../Concept/CAssociations/CAssociation[@type='composite' and @id_cchild=current()/@id_concept]">
            <xsl:value-of select="../../@name"/><xsl:text> </xsl:text>
          </xsl:for-each>). TODO: this now checks only if concept in a composite has at least two keys...
        </msg>
      </problem>
    </xsl:if>

    <xsl:apply-templates select="CProperties/CProperty"/>
    <xsl:apply-templates select="CAssociations/CAssociation"/>
  </xsl:template>

  <xsl:template match="CProperty">
    <xsl:if test="@type='varchar' or @type='char' or @type='file' or @type='longvarchar' or @type='password' or @type='url' or @type='xhtml'">
      <xsl:if test="not(@len) or @len=''">
        <problem type="ERROR" resource="Concept: {../../@name} Property: {@name}" link="object_model/?dp=edit103&amp;ID_Concept={../../@id_concept}&amp;ID_CProperty={@id_cproperty}">
          <msg>Property with textual data type has to have its length specified.</msg>
        </problem>
      </xsl:if>
    </xsl:if>
    <xsl:if test="@key='1'">
      <xsl:if test="@type!='char' and @len!='36'">
        <problem type="WARNING" resource="Concept: {../../@name}" link="object_model/?dp=edit103&amp;ID_Concept={../../@id_concept}&amp;ID_CProperty={@id_cproperty}">
          <msg>Key property is expected to be char(36), but it is <xsl:value-of select="concat(@type,'(',@len,')')"/>.</msg>
        </problem>
      </xsl:if>
      <xsl:if test="count(../CProperty[@key='1'])=1">
        <!-- if there is just one key -->
        <xsl:if test="@oncreate!='hide' and @onedit!='hide' and (not(@ref) or @ref='')">
          <problem type="WARNING" resource="Concept: {../../@name}" link="object_model/?dp=edit103&amp;ID_Concept={../../@id_concept}&amp;ID_CProperty={@id_cproperty}">
            <msg>Key property should be hidden both on edit and on create. TODO: What about dynamic enumerations?</msg>
          </problem>
        </xsl:if>
        <xsl:if test="@cntr!='1'">
          <problem type="WARNING" resource="Concept: {../../@name}" link="object_model/?dp=edit103&amp;ID_Concept={../../@id_concept}&amp;ID_CProperty={@id_cproperty}">
            <msg>Key property must have counter enabled. TODO: What about dynamic enumerations?</msg>
          </problem>
        </xsl:if>
        <xsl:if test="@name!=concat('ID_',../../@name)">
          <problem type="WARNING" resource="Concept: {../../@name}" link="object_model/?dp=edit103&amp;ID_Concept={../../@id_concept}&amp;ID_CProperty={@id_cproperty}">
            <msg>Key property should be named (by the current convention) as the concept name prefixed with ID_ (i.e. ID_Process).</msg>
          </problem>
        </xsl:if>
      </xsl:if>
    </xsl:if>
    <xsl:if test="@ref and @ref!=''">
      <xsl:choose>
        <xsl:when test="not(../../../Concept[@name=substring-before(current()/@ref, '/')])">
          <problem type="ERROR" resource="Concept: {../../@name} Property: {@name}" link="object_model/?dp=edit103&amp;ID_Concept={../../@id_concept}&amp;ID_CProperty={@id_cproperty}">
            <msg>Property <xsl:value-of select="@name"/> doesn't reference existing concept - <xsl:value-of select="@ref"/></msg>
          </problem>
        </xsl:when>
        <xsl:when test="not(../../../Concept[@name=substring-before(current()/@ref, '/')]/CProperties/CProperty[@name=substring-after(current()/@ref, '/')])">
          <problem type="ERROR" resource="Concept: {../../@name} Property: {@name}" link="object_model/?dp=edit103&amp;ID_Concept={../../@id_concept}&amp;ID_CProperty={@id_cproperty}">
            <msg>Property <xsl:value-of select="@name"/> doesn't reference existing property of concept <xsl:value-of select="substring-before(current()/@ref, '/')"/> - <xsl:value-of select="@ref"/></msg>
          </problem>
        </xsl:when>
      </xsl:choose>
      <xsl:if test="@fetchtype='direct' and count(../../../Concept[@name=substring-before(current()/@ref, '/')]/CProperties/CProperty[@onlabel='1'])&lt;1">
        <problem type="WARNING" resource="Concept: {../../@name}" link="object_model/?dp=edit103&amp;ID_Concept={../../@id_concept}&amp;ID_CProperty={@id_cproperty}">
          <msg>Property <xsl:value-of select="@name"/> has direct reference to concept that has nothing on label - <xsl:value-of select="@ref"/></msg>
        </problem>
      </xsl:if>
    </xsl:if>
    <xsl:if test="@fetchtype and @fetchtype='external' and (not(@ref) or @ref='')">
      <problem type="ERROR" resource="Concept: {../../@name} Property: {@name}" link="object_model/?dp=edit103&amp;ID_Concept={../../@id_concept}&amp;ID_CProperty={@id_cproperty}">
        <msg>Fetch type of property <xsl:value-of select="@name"/> requires nonempty reference.</msg>
      </problem>
    </xsl:if>
  </xsl:template>

  <xsl:template match="CAssociation">
    <xsl:if test="not(../../../Concept[@id_concept=current()/@id_cchild])">
      <problem type="ERROR" resource="Concept: {../../@name}" link="object_model/?dp=edit105&amp;ID_CParent={@id_cparent}&amp;ID_CChild={@id_cchild}">
        <msg>Association links to a non-existent concept.</msg>
      </problem>
    </xsl:if>
    <xsl:if test="not(CABindings/CABinding)">
      <problem type="ERROR" resource="Concept: {../../@name}" link="object_model/?dp=edit105&amp;ID_CParent={@id_cparent}&amp;ID_CChild={@id_cchild}">
        <msg>Association is missing bindings.</msg>
      </problem>
    </xsl:if>

    <xsl:apply-templates select="CABindings/CABinding"/>
  </xsl:template>

  <xsl:template match="CABinding">
    <xsl:if test="not(../../../../CProperties/CProperty[@name=current()/@p1])">
      <problem type="ERROR" resource="Concept: {../../../../@name}" link="object_model/?dp=list107&amp;ID_CParent={@id_cparent}&amp;ID_CChild={@id_cchild}&amp;ID_CAssociation={@id_cassociation}">
        <msg>Source concept of the association does not have property <xsl:value-of select="@p1"/> (p1).</msg>
      </problem>
    </xsl:if>
    <xsl:if test="not(../../../../../Concept[@id_concept=current()/@id_cchild]/CProperties/CProperty[@name=current()/@p2])">
      <problem type="ERROR" resource="Concept: {../../../../@name}" link="object_model/?dp=list107&amp;ID_CParent={@id_cparent}&amp;ID_CChild={@id_cchild}&amp;ID_CAssociation={@id_cassociation}">
        <msg>Target concept of the association does not have property <xsl:value-of select="@p2"/> (p2).</msg>
      </problem>
    </xsl:if>
  </xsl:template>

  <xsl:template match="CVInclude">
    <xsl:param name="root" select="."/>

    <xsl:variable name="link">cvincludes/?ID_CVInclude=<xsl:value-of select="@id_cvinclude"/>&amp;dp=edit111</xsl:variable>
    <xsl:variable name="linkchild">cvincludes/?ID_CVIParent=<xsl:value-of select="../../../../@id_cvinclude"/>&amp;ID_CVIChild=<xsl:value-of select="@id_cvinclude"/>&amp;dp=edit115</xsl:variable>

    <xsl:if test="name(..)='CVInclude' and @linkname!='-'">
      <problem type="WARNING" resource="CVInclude: {Title}" link="{$link}">
        <msg>Linkname in the root include should be set to "-" and not to "<xsl:value-of select="@linkname"/>".</msg>
      </problem>
    </xsl:if>
    <xsl:if test="name(..)!='CVInclude' and not(/node()/Concept/Concept[@id_concept=current()/../../../../@id_concept]/CAssociations/CAssociation[@linkname=current()/@linkname])">
      <problem type="ERROR" resource="CVInclude: {Title}" link="{$linkchild}">
        <msg>Linkname "<xsl:value-of select="@linkname"/>" was not found among associations of concept <xsl:text/>
          <xsl:value-of select="/node()/Concept/Concept[@id_concept=current()/../../../../@id_concept]/@name"/>. <xsl:text/>
        </msg>
      </problem>      
    </xsl:if>
    <xsl:if test="@hasflap='1'
              and /node()/Concept/Concept[@id_concept=current()/@id_concept]/CProperties/CProperty[@ref and @ref!='' and @fetchtype='external']
              and not(CVIProperties/CVIProperty[@extwork and @extwork!='' and @name=/node()/Concept/Concept[@id_concept=current()/@id_concept]/CProperties/CProperty[@ref and @ref!='' and @fetchtype='external']/@name])
              and /node()/CView/CView[@id_cvinclude=$root/@id_cvinclude]/@cangenerate='1'">
              <!-- TODO?: This: not(CVIProperties/CVIProperty[@extwork and @extwork!='' and @name=/node()/Concept/Concept[@id_concept=current()/@id_concept]/CProperties/CProperty[@ref and @ref!='' and @fetchtype='external']/@name])
                   may not work when more than one concept property has external reference -->
      <problem type="WARNING" resource="CVInclude: {Title}">
        <xsl:attribute name="link">
          <xsl:choose>
            <xsl:when test="name(..)='CVInclude'">
              <xsl:value-of select="$link"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="$linkchild"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:attribute>
        <msg>Include doesn't define external work for property with reference and external fetch type.</msg>
      </problem>
    </xsl:if>
    <xsl:if test="not(/node()/Concept/Concept[@id_concept=current()/@id_concept])">
      <problem type="ERROR" resource="CVInclude: {Title}">
        <xsl:attribute name="link">
          <xsl:choose>
            <xsl:when test="name(..)='CVInclude'">
              <xsl:value-of select="$link"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="$linkchild"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:attribute>
        <msg>Included concept doesn't exist.</msg>
      </problem>      
    </xsl:if>

    <xsl:apply-templates select="CVIProperties/CVIProperty"/>
    <xsl:apply-templates select="CVIStyles/CVIStyle"/>
    <xsl:apply-templates select="CVIRels/CVIRel/CVIncludes/CVInclude">
      <xsl:with-param name="root" select="$root"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="CVIProperty">
    <xsl:variable name="result">
      <xsl:call-template name="checkcvipname">
        <xsl:with-param name="cvi" select="../.."/>
        <xsl:with-param name="name" select="@name"/>
      </xsl:call-template>
    </xsl:variable>
    
    <xsl:if test="$result='invalid'">
      <problem type="ERROR" resource="CVIProperty: {@name}" link="cvincludes/?dp=edit112&amp;ID_CVInclude={@id_cvinclude}&amp;ID_CVIProperty={@id_cviproperty}">
        <msg>Concept view property has to correspond to some existing concept property. TODO: Properties fetched from object by external selections are not recognzied yet (only properties from sub-CVIncludes are)</msg>
      </problem>
    </xsl:if>
  </xsl:template>

  <xsl:template match="CVIStyle">
    <xsl:if test="not(/node()/Style/Style[@id_style=current()/@id_style])">
      <problem type="ERROR" resource="CVInclude: {../../Title}, Style: {@id_style}" link="cvincludes/?dp=edit18&amp;ID_CVInclude={../../@id_cvinclude}&amp;ID_Style={@id_style}">
        <msg>Style doesn't exist.</msg>
      </problem>
    </xsl:if>
  </xsl:template>

  <xsl:template match="CView">
    <xsl:if test="@cangenerate='1' and not(/node()/CVInclude/CVInclude[@id_cvinclude=current()/@id_cvinclude])">
      <problem type="ERROR" resource="CView: {@name}" link="cviews/?dp=edit118&amp;ID_CView={@id_cview}">
        <msg>Root include doesn't exist.</msg>
      </problem>
    </xsl:if>
  </xsl:template>

  <xsl:template match="MenuCat">
    <xsl:apply-templates select="MenuItems/MenuItem"/>
  </xsl:template>

  <xsl:template match="MenuItem">
    <xsl:if test="@id_cview and @id_cview!='' and not(/node()/CView/CView[@id_cview=current()/@id_cview])">
      <problem type="ERROR" resource="Menucat: {../../@name} Menuitem: {@id_menuitem}" link="menucats/?dp=edit3007594&amp;ID_MenuItem={@id_menuitem}&amp;ID_MenuCat={@id_menucat}">
        <msg>View bound to menu item doesn't exist.</msg>
      </problem>
    </xsl:if>

    <xsl:apply-templates select="MenuCats/MenuCat"/>
  </xsl:template>

  <xsl:template name="checkcvipname">
    <xsl:param name="cvi"/>
    <xsl:param name="name"/>
    
    <xsl:choose>
      <xsl:when test="contains($name, '/')">
        <xsl:choose>
          <xsl:when test="$cvi/CVIRels/CVIRel/CVIncludes/CVInclude[@nickname=substring-before($name, '/')]">
            <xsl:call-template name="checkcvipname">
              <xsl:with-param name="cvi" select="$cvi/CVIRels/CVIRel/CVIncludes/CVInclude[@nickname=substring-before($name, '/')]"/>
              <xsl:with-param name="name" select="substring-after($name, '/')"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:when test="$cvi/CVIRels/CVIRel/CVIncludes/CVInclude[@id_concept=/node()/Concept/Concept[@name=substring-before($name, '/')]/@id_concept]">
            <xsl:call-template name="checkcvipname">
              <xsl:with-param name="cvi" select="$cvi/CVIRels/CVIRel/CVIncludes/CVInclude[@id_concept=/node()/Concept/Concept[@name=substring-before($name, '/')]/@id_concept]"/>
              <xsl:with-param name="name" select="substring-after($name, '/')"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>invalid</xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:when test="/node()/Concept/Concept[@id_concept=$cvi/@id_concept]/CProperties/CProperty[@name=$name]"/>
      <xsl:otherwise>invalid</xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>
